package com.yugao.fintech.framework.lock;

import com.yugao.fintech.framework.lock.constant.LockBeanName;
import com.yugao.fintech.framework.lock.manager.CuratorManager;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.state.ConnectionState;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;

import javax.annotation.Resource;
import java.util.concurrent.CountDownLatch;

@AutoConfiguration
@ConditionalOnClass(CuratorFramework.class)
@EnableConfigurationProperties(CuratorProperties.class)
public class LyLockCuratorAutoConfiguration {
    private static final Logger log = LoggerFactory.getLogger(LyLockCuratorAutoConfiguration.class);

    @Resource
    private CuratorProperties curatorProperties;

    @Bean(name = LockBeanName.CURATOR_SERVICE)
    @ConditionalOnMissingBean(CuratorManager.class)
    public CuratorManager curatorService(CuratorFramework curatorFramework) {
        return new CuratorManager(curatorFramework);
    }

    @Bean
    @ConditionalOnMissingBean(CuratorFramework.class)
    public CuratorFramework curatorFramework() {
        CuratorProperties.RetryPolicy retryPolicy = curatorProperties.getRetryPolicy();
        // 重试策略, eg: 重试时间 3 秒, 重试 3 次
        RetryPolicy policy = new ExponentialBackoffRetry((int) retryPolicy.getBaseSleepTime().toMillis(), retryPolicy.getMaxRetries());
        // 通过工厂创建 Curator
        String connectString = curatorProperties.getAddress();
        long connectionTimeout = curatorProperties.getSessionTimeout().toMillis();
        long sessionTimeout = curatorProperties.getSessionTimeout().toMillis();
        CuratorFramework curatorFramework = CuratorFrameworkFactory.builder()
                .connectString(connectString)
                .connectionTimeoutMs((int) connectionTimeout)
                .sessionTimeoutMs((int) sessionTimeout)
                .retryPolicy(policy).build();
        CountDownLatch waitConnectionLatch = new CountDownLatch(1);
        curatorFramework.getConnectionStateListenable().addListener((client, newState) -> {
            if (newState == ConnectionState.CONNECTED) {
                log.info("curator connection zookeeper success！");
                waitConnectionLatch.countDown();
            }
        });
        log.info("curator connection zookeeper......");
        // 开启连接
        curatorFramework.start();
        try {
            waitConnectionLatch.await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return curatorFramework;
    }
}
